/*
 * Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "rtmp_common.h"
#include <cstdlib>
#include <cstring>
#include <netinet/in.h>

namespace OHOS {
namespace Sharing {
RtmpHandshake::RtmpHandshake(uint32_t _time, uint8_t *_random)
{
    _time = htonl(_time);
    memcpy(timestamp, &_time, 4);
    if (!_random) {
        RandomGenerate((char *)random, sizeof(random));
    } else {
        memcpy(random, _random, sizeof(random));
    }
}

void RtmpHandshake::RandomGenerate(char *bytes, int size)
{
    static char cdata[] = {0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x2d, 0x72, 0x74, 0x6d, 0x70, 0x2d,
                           0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2d, 0x77, 0x69, 0x6e, 0x6c, 0x69,
                           0x6e, 0x2d, 0x77, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x65, 0x72, 0x76,
                           0x65, 0x72, 0x40, 0x31, 0x32, 0x36, 0x2e, 0x63, 0x6f, 0x6d};
    for (int i = 0; i < size; i++) {
        bytes[i] = cdata[rand() % (sizeof(cdata) - 1)];
    }
}

RtmpPacket::Ptr RtmpPacket::Create()
{
    return RtmpPacket::Ptr(new RtmpPacket);
}

bool RtmpPacket::IsVideoKeyFrame() const
{
    return typeId == RTMPMessageType::VIDEO && (uint8_t)Peek()[0] >> 4 == FLV_KEY_FRAME && (uint8_t)Peek()[1] == 1;
}

void RtmpPacket::Clear()
{
    isAbsStamp = false;
    timestamp = 0;
    tsField = 0;
    bodySize = 0;
    DataBuffer::Clear();
}

bool RtmpPacket::IsCfgFrame() const
{
    switch (typeId) {
        case RTMPMessageType::VIDEO:
            return (uint8_t)Peek()[1] == 0; // SPS/PPS ???
        case RTMPMessageType::AUDIO: {
            switch (GetMediaType()) {
                case FLV_CODEC_AAC:
                    return (uint8_t)Peek()[1] == 0;
                default:
                    return false;
            }
        }
        default:
            return false;
    }
}

int RtmpPacket::GetMediaType() const
{
    switch (typeId) {
        case RTMPMessageType::VIDEO:
            return (uint8_t)Peek()[0] & 0x0F;
        case RTMPMessageType::AUDIO:
            return (uint8_t)Peek()[0] >> 4;
        default:
            return 0;
    }
}

int RtmpPacket::GetAudioSampleRate() const
{
    if (typeId != RTMPMessageType::AUDIO) {
        return 0;
    }
    int flvSampleRate = ((uint8_t)Peek()[0] & 0x0C) >> 2;
    const static int sampleRate[] = {5512, 11025, 22050, 44100};
    return sampleRate[flvSampleRate];
}

int RtmpPacket::GetAudioSampleBit() const
{
    if (typeId != RTMPMessageType::AUDIO) {
        return 0;
    }
    int flvSampleBit = ((uint8_t)Peek()[0] & 0x02) >> 1;
    const static int sampleBit[] = {8, 16};
    return sampleBit[flvSampleBit];
}

int RtmpPacket::GetAudioChannel() const
{
    if (typeId != RTMPMessageType::AUDIO) {
        return 0;
    }
    int flvStereoOrMono = (uint8_t)Peek()[0] & 0x01;
    const static int channel[] = {1, 2};
    return channel[flvStereoOrMono];
}

RtmpPacket &RtmpPacket::operator=(const RtmpPacket &that)
{
    isAbsStamp = that.isAbsStamp;
    streamId = that.streamId;
    bodySize = that.bodySize;
    typeId = that.typeId;
    tsField = that.tsField;
    timestamp = that.timestamp;
    return *this;
}
} // namespace Sharing
} // namespace OHOS